home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / x / volume3 / awm2 / part04 < prev    next >
Encoding:
Internet Message Format  |  1989-02-17  |  54.5 KB

  1. Path: uunet!wyse!mikew
  2. From: mikew@wyse.wyse.com (Mike Wexler)
  3. Newsgroups: comp.sources.x
  4. Subject: v03i020:  Ardent Window Manager, Patchlevel 9, Part04/12
  5. Message-ID: <2070@wyse.wyse.com>
  6. Date: 17 Feb 89 19:17:01 GMT
  7. Organization: Wyse Technology, San Jose
  8. Lines: 2229
  9. Approved: mikew@wyse.com
  10.  
  11. Submitted-by: kmw@ardent (Ken Wallich)
  12. Posting-number: Volume 3, Issue 20
  13. Archive-name: awm2/part04
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 4 (of 12)."
  22. # Contents:  GetButton.c Lock.c gram.y
  23. # Wrapped by mikew@wyse on Fri Feb 17 10:50:22 1989
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. if test -f 'GetButton.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'GetButton.c'\"
  27. else
  28. echo shar: Extracting \"'GetButton.c'\" \(22197 characters\)
  29. sed "s/^X//" >'GetButton.c' <<'END_OF_FILE'
  30. X
  31. X
  32. X
  33. X#ifndef lint
  34. Xstatic char *rcsid_GetButton_c = "$Header: /usr/graph2/X11.3/contrib/windowmgrs/awm/RCS/GetButton.c,v 1.3 89/02/07 22:39:19 jkh Exp $";
  35. X#endif    lint
  36. X
  37. X#include "X11/copyright.h"
  38. X/*
  39. X *
  40. X * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca.
  41. X *
  42. X * Copyright 1987 by Jordan Hubbard.
  43. X *
  44. X *
  45. X *                         All Rights Reserved
  46. X *
  47. X * Permission to use, copy, modify, and distribute this software and its
  48. X * documentation for any purpose and without fee is hereby granted,
  49. X * provided that the above copyright notice appear in all copies and that
  50. X * both that copyright notice and this permission notice appear in
  51. X * supporting documentation, and that the name of Ardent Computer
  52. X * Corporation or Jordan Hubbard not be used in advertising or publicity
  53. X * pertaining to distribution of the software without specific, written
  54. X * prior permission.
  55. X *
  56. X */
  57. X
  58. X/*
  59. X * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
  60. X *
  61. X *                         All Rights Reserved
  62. X *
  63. X * Permission to use, copy, modify, and distribute this software and its
  64. X * documentation for any purpose and without fee is hereby granted,
  65. X * provided that the above copyright notice appear in all copies and that
  66. X * both that copyright notice and this permission notice appear in
  67. X * supporting documentation, and that the name of Digital Equipment
  68. X * Corporation not be used in advertising or publicity pertaining to
  69. X * distribution of the software without specific, written prior permission.
  70. X *
  71. X *
  72. X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  73. X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  74. X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  75. X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  76. X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  77. X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  78. X * SOFTWARE.
  79. X */
  80. X
  81. X
  82. X
  83. X/*
  84. X * MODIFICATION HISTORY
  85. X *
  86. X * 000 -- M. Gancarz, DEC Ultrix Engineering Group
  87. X * 001 -- L. Guarino Reid, DEC Ultrix Engineering Group, Western Software Lab
  88. X *      February 16, 1987
  89. X *      Add EnterWindow, LeaveWindow, and MouseMotion as recognized
  90. X *      awm buttons for awm menus. Add bug fixes to prevent mem faults
  91. X *      if icon_str is NULL.
  92. X * 002 -- L. Guarino Reid, DEC Ultrix Engineering Group
  93. X *      April 16, 1987
  94. X *      Convert to X11
  95. X * 003 -- J. Hubbard, U.C. Berkeley. Title/gadget box event handling.
  96. X *    December 3, 1987.
  97. X * 004 -- J.Hubbard, Ardent Computer. More conformance with ICCCM. Merge of
  98. X * changes from R2 uwm.
  99. X */
  100. X
  101. X#ifndef lint
  102. Xstatic char *sccsid = "@(#)GetButton.c    3.8    1/24/86";
  103. X#endif
  104. X/*
  105. X *    GetButton - This subroutine is used by the Ardent Window Manager (awm)
  106. X *    to acquire button events.  It waits for a button event to occur
  107. X *    and handles all event traffic in the interim.
  108. X *
  109. X *    File:        GetButton.c
  110. X */
  111. X
  112. X#include "awm.h"
  113. X#include "X11/Xutil.h"
  114. X
  115. Xextern XContext AwmContext;
  116. Xextern Window FocusWindow;
  117. X
  118. X#define ICONSTR    (icon_str ? icon_str : "")
  119. X/* Amount of padding between text in a title bar and the edge of the bar */
  120. X#define PAD    1
  121. X
  122. Xstatic Icon_modified = FALSE;
  123. X
  124. XBoolean GetButton(b_ev)
  125. XXEvent *b_ev;    /* Button event packet. */
  126. X{
  127. X#define STRLEN 50
  128. X     char *icon_str;        /* Icon's name string. */
  129. X     register int icon_str_len;    /* Icon name string lenght.  */
  130. X     register int key_char;    /* Key press character code. */
  131. X     register int icon_x;    /* Icon window X coordinate. */
  132. X     register int icon_y;    /* Icon window Y coordinate. */
  133. X     register unsigned int icon_w;    /* Icon window width. */
  134. X     register unsigned int icon_h;    /* Icon window height. */    
  135. X     int status;            /* Routine call return status. */
  136. X     Window icon;        /* Icon window. */
  137. X     XWindowAttributes win_info;    /* Icon window info structure. */
  138. X     char kbd_str[STRLEN];      /* Keyboard string. */
  139. X     int nbytes;                /* Keyboard string length. */
  140. X     int i;                     /* Iteration counter. */
  141. X     Window win;        /* scratch */
  142. X     AwmInfoPtr awi;
  143. X     extern char *GetTitleName();
  144. X     
  145. X     Entry("GetButton")
  146. X  
  147. X     /*
  148. X      * Get next event from input queue and store it in the event packet
  149. X      * passed to GetButton.
  150. X      */
  151. X  
  152. X     XNextEvent(dpy, b_ev);
  153. X     /* print_event_info("mainloop", b_ev); /* debugging for event handling */
  154. X
  155. X     /*
  156. X      * The event occured on the root window, check for substructure
  157. X      * changes. Otherwise, it must be a mouse button event. 
  158. X      */
  159. X
  160. X     if (b_ev->xany.window == RootWindow(dpy, scr)) {
  161. X      switch (b_ev->xany.type) {
  162. X      case CreateNotify:
  163. X      case UnmapNotify:
  164. X      case ReparentNotify:
  165. X      case ConfigureNotify:
  166. X      case GravityNotify:
  167. X      case MapNotify:
  168. X      case CirculateNotify:
  169. X           Leave(FALSE)
  170. X            
  171. X      case MappingNotify:
  172. X           XRefreshKeyboardMapping((XMappingEvent *) b_ev);
  173. X           Leave(FALSE)
  174. X
  175. X      case MapRequest: 
  176. X           CheckMap(b_ev->xmap.window);
  177. X           Leave(FALSE)
  178. X
  179. X      case ConfigureRequest: 
  180. X           Configure((XConfigureRequestEvent *)b_ev);
  181. X           Leave(FALSE)
  182. X           
  183. X      case CirculateRequest: 
  184. X           Circulate((XCirculateEvent *)b_ev);
  185. X           Leave(FALSE)
  186. X           
  187. X      case DestroyNotify:
  188. X           RemoveIcon(b_ev->xdestroywindow.window);
  189. X           Leave(FALSE)
  190. X
  191. X      case FocusIn:
  192. X           if (b_ev->xfocus.detail == NotifyPointerRoot) {
  193. X            if (FocusSetByUser) {
  194. X             XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot,
  195. X                    CurrentTime);
  196. X             FocusSetByUser = FALSE;
  197. X             FocusWindow = RootWindow(dpy, scr);
  198. X            }
  199. X           }
  200. X           Leave(FALSE)
  201. X           
  202. X      case FocusOut:
  203. X           if (b_ev->xfocus.detail == NotifyPointerRoot) {
  204. X            if (FocusSetByUser == FALSE && !FocusSetByWM) {
  205. X             XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot,
  206. X                    CurrentTime);
  207. X             FocusWindow = RootWindow(dpy, scr);
  208. X            }
  209. X           }
  210. X           Leave(FALSE)
  211. X           
  212. X      case ButtonPress:
  213. X      case ButtonRelease:
  214. X           Leave(TRUE)
  215. X
  216. X      default: 
  217. X           Leave(FALSE) 
  218. X      }
  219. X     }
  220. X     
  221. X     /*
  222. X      * If the event type is EnterWindow, LeaveWindow, or MouseMoved,
  223. X      * we are processing a menu. 
  224. X      * If the event type is ButtonPress or ButtonRelease,
  225. X      * we have a button event.
  226. X      * If it's an expose, then we may have exposed a title bar.
  227. X      * If it's a Notify, we've probably frobbed a titled window.
  228. X      */
  229. X     
  230. X     switch (b_ev->type) {
  231. X      XEvent e_fake;
  232. X
  233. X     case MotionNotify: 
  234. X     case ButtonPress: 
  235. X     case ButtonRelease: 
  236. X      Leave(TRUE)
  237. X      break;
  238. X
  239. X     case FocusIn:
  240. X      if (!FocusSetByWM) {
  241. X           e_fake.xcrossing.type = FocusIn;
  242. X           e_fake.xcrossing.focus = TRUE;
  243. X           e_fake.xcrossing.window = b_ev->xcrossing.window;
  244. X           HandleFocusIn(&e_fake);
  245. X      }
  246. X      Leave(FALSE)
  247. X      break;
  248. X
  249. X     case FocusOut:
  250. X      if (!FocusSetByWM) {
  251. X           e_fake.xcrossing.type = FocusOut;
  252. X           e_fake.xcrossing.focus = TRUE;
  253. X           e_fake.xcrossing.window = b_ev->xcrossing.window;
  254. X           HandleFocusOut(&e_fake);
  255. X      }
  256. X      Leave(FALSE)
  257. X      break;
  258. X      
  259. X     case EnterNotify:
  260. X      HandleFocusIn(b_ev);
  261. X      Leave(FALSE)
  262. X
  263. X     case LeaveNotify: 
  264. X      HandleFocusOut(b_ev);
  265. X      Leave(FALSE)
  266. X
  267. X     case ConfigureRequest:
  268. X      Configure((XConfigureRequestEvent *)b_ev);
  269. X      Leave(FALSE)
  270. X
  271. X     case MapRequest:
  272. X      CheckMap(b_ev->xmap.window);
  273. X      Leave(FALSE);
  274. X
  275. X     case MapNotify:
  276. X          Leave(FALSE)
  277. X      break;
  278. X      
  279. X     case UnmapNotify:
  280. X      win = b_ev->xunmap.window;
  281. X          if (!(awi = GetAwmInfo(win)))
  282. X              Leave(FALSE)
  283. X
  284. X      if (IsIcon(win, None))
  285. X           Leave(FALSE)
  286. X       XUnmapWindow(dpy, awi->frame);
  287. X      Leave(FALSE)
  288. X      break;
  289. X
  290. X     case DestroyNotify:
  291. X      win = b_ev->xdestroywindow.window;
  292. X          if (!(awi = GetAwmInfo(win)))
  293. X              Leave(FALSE)
  294. X      if (win != awi->title) {
  295. X           /* remove any icon associated with this window */
  296. X           RemoveIcon(win);
  297. X           /* remove the frame/titlebar (if present) */
  298. X           NoDecorate(win, TRUE);
  299. X           /* punt the rest of the per-window info */
  300. X           XDeleteContext(dpy, awi->client, AwmContext);
  301. X           free(awi);
  302. X      }
  303. X          Leave(FALSE)
  304. X
  305. X     case PropertyNotify:
  306. X      win = b_ev->xproperty.window;
  307. X          if (!(awi = GetAwmInfo(win)))
  308. X               Leave(FALSE);
  309. X#ifdef WMSTATE
  310. X      if (!(b_ev->xproperty.atom==wm_state_atom)) /* ignore state change */
  311. X#endif /* WMSTATE */
  312. X      switch(b_ev->xproperty.atom) {
  313. X
  314. X      case XA_WM_COMMAND:
  315. X      case XA_WM_HINTS:
  316. X      case XA_WM_CLIENT_MACHINE:
  317. X           break;
  318. X
  319. X      case XA_WM_ICON_NAME:
  320. X           if (Icon_modified == TRUE) {
  321. X            /*
  322. X             * Icon was modified by type-in (I still think that's a
  323. X             * gross feature, but some people like it... sigh),
  324. X             * ignore this event.
  325. X             */
  326. X            Icon_modified = FALSE;    /* reset */
  327. X            Leave(FALSE)
  328. X           }
  329. X           /*
  330. X        * Icon was modifed in a more civilized fashion.
  331. X        */
  332. X           if (awi->icon && awi->own && awi->iconPixmap == IBackPixmap) {
  333. X            win = awi->icon;
  334. X            status = XGetWindowAttributes(dpy, win, &win_info);
  335. X            icon_str = GetIconName(awi->client);
  336. X            icon_str_len = icon_str ? strlen(icon_str) : 0;
  337. X            if (win_info.width != XTextWidth(IFontInfo, ICONSTR,
  338. X                             strlen(ICONSTR)) +
  339. X            (HIconPad << 1)) {
  340. X             XResizeWindow(dpy, win, 
  341. X                       XTextWidth(IFontInfo, ICONSTR,
  342. X                          strlen(ICONSTR)) +
  343. X                       (HIconPad << 1), IFontInfo->ascent +
  344. X                       IFontInfo->descent + (VIconPad << 1));
  345. X            }
  346. X            XClearWindow(dpy, win);
  347. X            if (icon_str_len != 0) {
  348. X             XDrawImageString(dpy, win, IconGC, HIconPad,
  349. X                      VIconPad+IFontInfo->ascent, icon_str,
  350. X                      icon_str_len);
  351. X             free(icon_str);
  352. X            }
  353. X           }
  354. X           break;
  355. X
  356. X      case XA_WM_ICON_SIZE:
  357. X           break;
  358. X
  359. X      case XA_WM_NAME:
  360. X           if (awi->title) {
  361. X            if (awi->name)
  362. X             free(awi->name);
  363. X            awi->name = GetTitleName(win);
  364. X            PaintTitle(win, (FocusWindow == awi->client));
  365. X           }
  366. X           break;
  367. X
  368. X      case XA_WM_NORMAL_HINTS:
  369. X      case XA_WM_SIZE_HINTS:
  370. X      case XA_WM_ZOOM_HINTS:
  371. X           break;
  372. X
  373. X      default:
  374. X           fprintf(stderr, "awm: Got unknown property %d\n",
  375. X               b_ev->xproperty.atom);
  376. X      }
  377. X      Leave(FALSE)
  378. X      break;
  379. X      
  380. X      
  381. X     case Expose:
  382. X      win = b_ev->xexpose.window;
  383. X          if (!(awi = GetAwmInfo(win))) /* probably a menu */
  384. X               Leave(FALSE)
  385. X      if (awi->title == win) {
  386. X           if (b_ev->xexpose.count == 0) {
  387. X            XEvent evt;
  388. X
  389. X            /* Eat up any previous exposes */
  390. X            while (XCheckTypedWindowEvent(dpy, awi->title, Expose,
  391. X                          &evt));
  392. X            PaintTitle(win, (FocusWindow == awi->client));
  393. X            if (awi->gadgets)
  394. X             PaintGadgets(win);
  395. X           }
  396. X           Leave(FALSE)
  397. X      }
  398. X      break;
  399. X      
  400. X     default:
  401. X      break;
  402. X     }
  403. X     
  404. X     /*
  405. X      * If we got this far, the event must be for an icon.
  406. X      */
  407. X     win = b_ev->xany.window;
  408. X     if (!(awi = GetAwmInfo(win)))
  409. X          Leave(FALSE)
  410. X     status = XGetWindowAttributes(dpy, win, &win_info);
  411. X     if (status == FAILURE)
  412. X      Leave(FALSE)
  413. X     
  414. X     if (b_ev->type == MapNotify || 
  415. X     b_ev->type == UnmapNotify ||
  416. X     b_ev->type == CreateNotify ||
  417. X     b_ev->type == ReparentNotify ||
  418. X     b_ev->type == GravityNotify ||
  419. X     b_ev->type == CirculateNotify ||
  420. X     b_ev->type == ConfigureNotify)
  421. X      Leave(FALSE)
  422. X     
  423. X     /*
  424. X      * Initialize the icon position variables.
  425. X      */
  426. X     icon_x = win_info.x;
  427. X     icon_y = win_info.y;
  428. X     
  429. X     /*
  430. X      * Get the name of the window associated with the icon and
  431. X      * determine its length.
  432. X      */
  433. X     if (!awi->icon)
  434. X      Leave(FALSE)
  435. X     /*
  436. X      * If we don't own it, or it's got a background pixmap, we don't have
  437. X      * to repaint it.
  438. X      */
  439. X     if (!awi->own || (awi->iconPixmap != IBackPixmap))
  440. X      Leave(FALSE)
  441. X     icon = awi->icon;
  442. X     icon_str = GetIconName(awi->client);
  443. X     icon_str_len = icon_str ? strlen(icon_str) : 0;
  444. X     
  445. X     /*
  446. X      * If the event is a window exposure event and the icon's name string
  447. X      * is not of zero length, simply repaint the text in the icon window
  448. X      * and return FALSE.
  449. X      */
  450. X     if (b_ev->type == Expose && (!Freeze || Frozen == 0)) {
  451. X      if (win_info.width != XTextWidth(IFontInfo, ICONSTR,
  452. X                       strlen(ICONSTR))+(HIconPad << 1)) {
  453. X           XResizeWindow(dpy, icon, 
  454. X                 XTextWidth(IFontInfo, ICONSTR,
  455. X                    strlen(ICONSTR)) + (HIconPad << 1),
  456. X                 IFontInfo->ascent + IFontInfo->descent + 
  457. X                 (VIconPad << 1));
  458. X      }
  459. X      XClearWindow(dpy, icon);
  460. X      if (icon_str_len != 0) {
  461. X           XDrawImageString(dpy, icon,
  462. X                IconGC, HIconPad, VIconPad+IFontInfo->ascent,
  463. X                icon_str, icon_str_len);
  464. X           /*
  465. X        * Remember to free the icon name string.
  466. X        */
  467. X           free(icon_str);
  468. X      }
  469. X      Leave(FALSE)
  470. X     }
  471. X
  472. X#ifndef NO_ICON_TYPIN     
  473. X     /*
  474. X      * If we have gotten this far event can only be a key pressed event.
  475. X      */
  476. X     
  477. X     /* 
  478. X      * We convert the key pressed event to ascii.
  479. X      */
  480. X     nbytes = XLookupString((XKeyEvent *)b_ev, kbd_str, STRLEN,
  481. X                (KeySym *) NULL, (XComposeStatus *) NULL);
  482. X     
  483. X     /*
  484. X      * If kbd_str is a "non-string", then don't do anything.
  485. X      */
  486. X     if (nbytes == 0 || !kbd_str || !*kbd_str) {
  487. X      if (icon_str)
  488. X           free(icon_str);
  489. X      Leave(FALSE)
  490. X     }
  491. X     for (i = 0; i < nbytes; i++) {
  492. X      key_char = kbd_str[i];
  493. X      /*
  494. X       * If the key was <DELETE>, then delete a character from the end of
  495. X       * the name, return FALSE.
  496. X       *
  497. X       * If the key was <CTRL-U>, then wipe out the entire window name
  498. X       * and return FALSE.
  499. X       *
  500. X       * All other ctrl keys are squashed and we return FALSE.
  501. X       *
  502. X       * All printable characters are appended to the window's name, which
  503. X       * may have to be grown to allow for the extra length.
  504. X       */
  505. X      if (key_char == '\177') {
  506. X           /*
  507. X        * <DELETE>
  508. X        */
  509. X           if (icon_str_len > 0) {
  510. X            icon_str_len--;
  511. X            icon_str[icon_str_len] = '\0';
  512. X           }
  513. X      }
  514. X      else if (key_char == '\025') {
  515. X           /*
  516. X        * <CTRL-U>
  517. X        */
  518. X           if (icon_str_len > 0) {
  519. X            icon_str_len = 0;
  520. X            icon_str[0] = '\0';
  521. X           }
  522. X      }
  523. X      else if (key_char < IFontInfo->min_char_or_byte2 ||
  524. X           key_char > IFontInfo->max_char_or_byte2) {
  525. X           /*
  526. X        * Any other random (non-printable) key; ignore it.
  527. X        */
  528. X           /* do nothing */ ;
  529. X               }
  530. X      else {
  531. X           /*
  532. X        * ASCII Alphanumerics.
  533. X        */
  534. X           if (icon_str == NULL)
  535. X            icon_str = (char *) malloc (icon_str_len + 2);
  536. X           else
  537. X            icon_str = (char *)realloc(icon_str, (icon_str_len + 2));
  538. X           if (icon_str == NULL) {
  539. X            errno = ENOMEM;
  540. X            Error("GetButton -> Realloc of window name string memory failed.");
  541. X           }
  542. X           icon_str[icon_str_len] = key_char;
  543. X           icon_str[icon_str_len + 1] = '\0';
  544. X           icon_str_len += 1;
  545. X      }
  546. X     }
  547. X     
  548. X     /*
  549. X      * Now that we have changed the size of the icon we have to reconfigure
  550. X      * it so that everything looks good.  Oh yes, don't forget to move the
  551. X      * mouse so that it stays in the window!
  552. X      */
  553. X     
  554. X     /*
  555. X      * Set the window name to the new string. Icon_modified is a kludge
  556. X      * that tells us to avoid the next PropertyNotify, as it's a result of
  557. X      * this call.
  558. X      */
  559. X     XSetIconName(dpy, awi->client, ICONSTR);
  560. X     Icon_modified = TRUE;
  561. X     /*
  562. X      * Determine the new icon window configuration.
  563. X      */
  564. X     icon_h = IFontInfo->ascent + IFontInfo->descent + (VIconPad << 1);
  565. X     icon_w = XTextWidth(IFontInfo, ICONSTR, strlen(ICONSTR));
  566. X     if (icon_w == 0) {
  567. X      icon_w = icon_h;
  568. X     }
  569. X     else {
  570. X      icon_w += (HIconPad << 1);
  571. X     }
  572. X     
  573. X     if (icon_x < 0) icon_x = 0;
  574. X     if (icon_y < 0) icon_y = 0;
  575. X     if (icon_x - 1 + icon_w + (IBorderWidth << 1) > ScreenWidth) {
  576. X      icon_x = ScreenWidth - icon_w - (IBorderWidth << 1) + 1;
  577. X     }
  578. X     if (icon_y - 1 + icon_h + (IBorderWidth << 1) > ScreenHeight) {
  579. X      icon_y = ScreenHeight - icon_h - (IBorderWidth << 1) + 1;
  580. X     }
  581. X     
  582. X     XMoveResizeWindow(dpy, icon, icon_x, icon_y, icon_w, icon_h);
  583. X     XWarpPointer(dpy, None, icon, 
  584. X          0, 0, 0, 0, (icon_w >> 1), (icon_h >> 1));
  585. X     
  586. X     /* 
  587. X      * Free the local storage and return FALSE.
  588. X      */
  589. X     if (icon_str)
  590. X      free(icon_str);
  591. X#endif
  592. X     Leave(FALSE)
  593. X}
  594. X
  595. XCheckMap(window)
  596. XWindow window;
  597. X{
  598. X     XWMHints *XGetWMHints();
  599. X     XWMHints *wmhints;
  600. X     Window transient_for = None;
  601. X     Binding *bptr;
  602. X     AwmInfoPtr awi;
  603. X     long event_mask;
  604. X
  605. X     Entry("CheckMap")
  606. X
  607. X     /* if it's a transient window, we won't rubber-band
  608. X      * note that this call always sets transient_for.
  609. X      */
  610. X     if (!XGetTransientForHint( dpy, window, &transient_for )) {
  611. X      /*
  612. X       * Handle any registered grabs for this window. We do this here
  613. X       * because we may be about to make an icon out of this window
  614. X       * and we want to register any potential grabs on it before this
  615. X       * happens.
  616. X       */
  617. X      awi = GetAwmInfo(window);
  618. X      if (!awi) {
  619. X           for (bptr = Blist; bptr; bptr = bptr->next)
  620. X            if (bptr->context & WINDOW)
  621. X             Grab(bptr->mask, window);
  622. X           awi = RegisterWindow(window);
  623. X           Decorate(awi->client);
  624. X           event_mask = PropertyChangeMask | FocusChangeMask;
  625. X           if (!FrameFocus)
  626. X            event_mask |= (EnterWindowMask | LeaveWindowMask);
  627. X           XSelectInput(dpy, window, event_mask);
  628. X#ifndef RAINBOW
  629. X           SetBorderPixmaps(awi, GrayPixmap);
  630. X#else
  631. X           SetBorderPixmaps(awi, awi->grayPixmap);
  632. X#endif
  633. X      }
  634. X      if ((wmhints = XGetWMHints(dpy, window))) {
  635. X           if ((wmhints->flags & StateHint) && (awi->state & ST_WINDOW) &&
  636. X           (wmhints->initial_state == IconicState)) {
  637. X            /* window wants to be created as an icon. Leave size
  638. X               /* and position alone, create as icon. */
  639. X                         XFree(wmhints);
  640. X                         Iconify(window, 0, 0, 0, 0);
  641. X                         Leave_void
  642. X           }
  643. X           XFree(wmhints);
  644. X      }
  645. X     }
  646. X     else { /* It's a transient */
  647. X      if (!(awi = GetAwmInfo(window)))
  648. X           awi = RegisterWindow(window);
  649. X      awi->attrs = AT_NONE;
  650. X      if (transient_for == None)
  651. X           transient_for = RootWindow(dpy, scr);
  652. X     }
  653. X     if (awi->state & ST_WINDOW) {
  654. X      PlaceWindow(window, transient_for);
  655. X      if (awi->frame) {
  656. X           XMapRaised(dpy, awi->frame);
  657. X           XMapWindow(dpy, awi->client);
  658. X      }
  659. X      else
  660. X           XMapRaised(dpy, awi->client);
  661. X      XSync(dpy, 0);
  662. X     }
  663. X     Leave_void
  664. X}
  665. X
  666. XConfigure(event)
  667. XXConfigureRequestEvent *event;
  668. X{
  669. X     XWindowChanges values;
  670. X     
  671. X     Entry("Configure")
  672. X
  673. X     values.x = event->x;
  674. X     values.y = event->y;
  675. X     values.width = event->width;
  676. X     values.height = event->height;
  677. X     values.border_width = event->border_width;
  678. X     values.stack_mode = event->detail;
  679. X     values.sibling = event->above;
  680. X
  681. X     ConfigureWindow(event->window, event->value_mask, &values);
  682. X     Leave_void
  683. X}
  684. X
  685. XCirculate(event)
  686. XXCirculateEvent *event;
  687. X{
  688. X     Entry("Circulate")
  689. X
  690. X     if (event->place == PlaceOnTop)
  691. X      XRaiseWindow(event->display, event->window);
  692. X     else
  693. X      XLowerWindow(event->display, event->window);
  694. X     Leave_void
  695. X}
  696. X
  697. XPlaceWindow(window, transient)
  698. XWindow window;
  699. XWindow transient;
  700. X{
  701. X     XSizeHints wsh;
  702. X     int x, y;
  703. X     unsigned int w, h;
  704. X     XWindowChanges xwc;
  705. X     AwmInfoPtr awi;
  706. X     unsigned long flags;
  707. X
  708. X     wsh.flags = 0;
  709. X     flags = CWX | CWY | CWWidth | CWHeight;
  710. X     awi = GetAwmInfo(window);
  711. X     XGetSizeHints(dpy, window, &wsh, XA_WM_NORMAL_HINTS);
  712. X     CheckConsistency(&wsh);
  713. X     AskUser(dpy, scr, window, &x, &y, &w, &h, &wsh, transient);
  714. X
  715. X     wsh.flags |= (USPosition | USSize);
  716. X     wsh.x = x;
  717. X     wsh.y = y;
  718. X     wsh.width = w;
  719. X     wsh.height = h;
  720. X     if (x < 0 || y < 0) {
  721. X      Window jW;
  722. X      int j, border_width;
  723. X
  724. X      XGetGeometry(dpy, window, &jW, &j, &j, &j, &j, &border_width, &j);
  725. X
  726. X      if (x < 0)
  727. X           x += DisplayWidth(dpy, scr) - w - (border_width<<1);
  728. X      if (y < 0)
  729. X           y += DisplayHeight(dpy, scr) - h - (border_width<<1);
  730. X     }
  731. X     if (awi->frame)
  732. X      XSetSizeHints(dpy, awi->frame, &wsh, XA_WM_NORMAL_HINTS);
  733. X     XSetSizeHints(dpy, awi->client, &wsh, XA_WM_NORMAL_HINTS);
  734. X#ifdef titan /* 5x4 alignment */
  735. X     x = ((x+3) / 5) * 5;
  736. X     y = ((y+2) / 4) * 4;
  737. X#endif
  738. X     xwc.x = x;
  739. X     xwc.y = y;
  740. X     xwc.height = h;
  741. X     xwc.width = w;
  742. X     ConfigureWindow(window, flags, &xwc);
  743. X     awi->state |= ST_PLACED;
  744. X}
  745. X
  746. XBoolean ConfigureWindow(w, mask, xwc)
  747. XWindow w;
  748. Xunsigned int mask;
  749. XXWindowChanges *xwc;
  750. X{
  751. X     AwmInfoPtr awi;
  752. X     int height, width, x, y;
  753. X     int bch = 0, bcv = 0;
  754. X     Entry("ConfigureWindow")
  755. X
  756. X     awi = GetAwmInfo(w);
  757. X     if (!awi) {
  758. X      /*
  759. X       * Make sure XtRealize gets its configure event. We'll actually
  760. X       * do another configure before we map, but this fakes XtRealize
  761. X       * into not waiting around for the configure notify.
  762. X       */
  763. X      XConfigureWindow(dpy, w, mask, xwc);
  764. X      XFlush(dpy);
  765. X          Leave(FALSE)
  766. X     }
  767. X
  768. X     if (awi->icon == w) {
  769. X      XConfigureWindow(dpy, w, mask, xwc);
  770. X      Leave(TRUE)
  771. X     }
  772. X     if (awi->attrs & AT_BORDER && DECORATED(awi)) {
  773. X      bcv = BContext + 1;
  774. X      bch = bcv * 2;
  775. X     }
  776. X
  777. X     height = xwc->height;
  778. X     width = xwc->width;
  779. X     if (awi->frame)
  780. X      x = y = 0;
  781. X     else {
  782. X      x = xwc->x;
  783. X      y = xwc->y;
  784. X     }
  785. X     /* width */
  786. X     xwc->width += bch;
  787. X     if (awi->title)
  788. X      XResizeWindow(dpy, awi->title, (unsigned) xwc->width, 
  789. X            (unsigned) titleHeight);
  790. X     /* height */
  791. X     if (DECORATED(awi)) {
  792. X      if (awi->attrs & AT_TITLE) {
  793. X           y = titleHeight + 2;
  794. X           xwc->height += y;
  795. X      }
  796. X      if (awi->attrs & AT_BORDER) {
  797. X           if (!(awi->attrs & AT_TITLE)) {
  798. X            xwc->height += (bcv * 2);
  799. X            y = bcv;
  800. X           }
  801. X           else
  802. X            xwc->height += bcv;
  803. X           xwc->x -= (BContext + (awi->border_width ? awi->border_width :
  804. X                      1));
  805. X           x = BContext;
  806. X      }
  807. X     }
  808. X     if (PushDown == FALSE) {
  809. X      if (awi->attrs & AT_TITLE && DECORATED(awi))
  810. X           xwc->y -= (titleHeight + 2);
  811. X      else if (awi->attrs & AT_BORDER && DECORATED(awi))
  812. X           xwc->y -= (BContext + (awi->border_width ?
  813. X                      awi->border_width : 1));
  814. X     }
  815. X     if (awi->frame)
  816. X          XConfigureWindow(dpy, awi->frame, mask, xwc);
  817. X     if (awi->gadgets)
  818. X      PutGadgets(w);
  819. X     xwc->width = width;
  820. X     xwc->height = height;
  821. X     xwc->x = x;
  822. X     xwc->y = y;
  823. X     XConfigureWindow(dpy, awi->client, mask, xwc);
  824. X     Leave(TRUE)
  825. X}
  826. X
  827. Xint
  828. XProcessRequests(box, num_vectors)
  829. XXSegment *box;
  830. Xint num_vectors;
  831. X{
  832. X    XEvent event;
  833. X
  834. X    XPeekEvent(dpy, &event);
  835. X    switch (event.type) {
  836. X
  837. X    case MapRequest:
  838. X    case ConfigureRequest:
  839. X    case CirculateRequest:
  840. X
  841. X        DrawBox();
  842. X        GetButton(&event);
  843. X        DrawBox();
  844. X        return TRUE;
  845. X    }
  846. X    return FALSE;
  847. X}
  848. END_OF_FILE
  849. if test 22197 -ne `wc -c <'GetButton.c'`; then
  850.     echo shar: \"'GetButton.c'\" unpacked with wrong size!
  851. fi
  852. # end of 'GetButton.c'
  853. fi
  854. if test -f 'Lock.c' -a "${1}" != "-c" ; then 
  855.   echo shar: Will not clobber existing file \"'Lock.c'\"
  856. else
  857. echo shar: Extracting \"'Lock.c'\" \(1627 characters\)
  858. sed "s/^X//" >'Lock.c' <<'END_OF_FILE'
  859. X
  860. X
  861. X
  862. X#ifndef lint
  863. Xstatic char *rcsid_Lower_c = "$Header: /usr/graph2/X11.3/contrib/windowmgrs/awm/RCS/Lock.c,v 1.2 89/02/07 21:22:31 jkh Exp $";
  864. X#endif    lint
  865. X
  866. X#include "X11/copyright.h"
  867. X/*
  868. X *
  869. X * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca.
  870. X *
  871. X * Copyright 1988 by Jordan Hubbard.
  872. X *
  873. X *
  874. X *                         All Rights Reserved
  875. X *
  876. X * Permission to use, copy, modify, and distribute this software and its
  877. X * documentation for any purpose and without fee is hereby granted,
  878. X * provided that the above copyright notice appear in all copies and that
  879. X * both that copyright notice and this permission notice appear in
  880. X * supporting documentation, and that the name of Ardent Computer
  881. X * Corporation or Jordan Hubbard not be used in advertising or publicity
  882. X * pertaining to distribution of the software without specific, written
  883. X * prior permission.
  884. X *
  885. X */
  886. X
  887. X/*
  888. X * MODIFICATION HISTORY
  889. X *
  890. X * 000 -- J.Hubbard, PCS Computer systems.
  891. X */
  892. X
  893. X#include "awm.h"
  894. X
  895. X#ifdef LOCKSCR
  896. X/*ARGSUSED*/
  897. XBoolean Lock(window, mask, button, x, y)
  898. XWindow window;                /* Event window. */
  899. Xint mask;                /* Button/key mask. */
  900. Xint button;                /* Button event detail. */
  901. Xint x, y;                /* Event mouse position. */
  902. X{
  903. X     void lockscreen();
  904. X
  905. X     Entry("Lock")
  906. X
  907. X     lockscreen(dpy);
  908. X     Leave(TRUE)
  909. X}
  910. X#else
  911. XBoolean Lock(window, mask, button, x, y)
  912. XWindow window;                /* Event window. */
  913. Xint mask;                /* Button/key mask. */
  914. Xint button;                /* Button event detail. */
  915. Xint x, y;                /* Event mouse position. */
  916. X{
  917. X     fprintf(stderr,
  918. X    "awm: You don't have lockscreen compiled in this version of awm.\n");
  919. X     Leave(FALSE)
  920. X}
  921. X#endif /* LOCKSCR */
  922. END_OF_FILE
  923. if test 1627 -ne `wc -c <'Lock.c'`; then
  924.     echo shar: \"'Lock.c'\" unpacked with wrong size!
  925. fi
  926. # end of 'Lock.c'
  927. fi
  928. if test -f 'gram.y' -a "${1}" != "-c" ; then 
  929.   echo shar: Will not clobber existing file \"'gram.y'\"
  930. else
  931. echo shar: Extracting \"'gram.y'\" \(27303 characters\)
  932. sed "s/^X//" >'gram.y' <<'END_OF_FILE'
  933. X/*
  934. X *
  935. X * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca.
  936. X *
  937. X * Copyright 1987 by Jordan Hubbard.
  938. X *
  939. X *
  940. X *                         All Rights Reserved
  941. X *
  942. X * Permission to use, copy, modify, and distribute this software and its
  943. X * documentation for any purpose and without fee is hereby granted,
  944. X * provided that the above copyright notice appear in all copies and that
  945. X * both that copyright notice and this permission notice appear in
  946. X * supporting documentation, and that the name of Ardent Computer
  947. X * Corporation or Jordan Hubbard not be used in advertising or publicity
  948. X * pertaining to distribution of the software without specific, written
  949. X * prior permission.
  950. X *
  951. X */
  952. X
  953. X/*
  954. X * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
  955. X *
  956. X *                         All Rights Reserved
  957. X *
  958. X * Permission to use, copy, modify, and distribute this software and its
  959. X * documentation for any purpose and without fee is hereby granted,
  960. X * provided that the above copyright notice appear in all copies and that
  961. X * both that copyright notice and this permission notice appear in
  962. X * supporting documentation, and that the name of Digital Equipment
  963. X * Corporation not be used in advertising or publicity pertaining to
  964. X * distribution of the software without specific, written prior permission.
  965. X *
  966. X *
  967. X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  968. X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  969. X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  970. X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  971. X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  972. X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  973. X * SOFTWARE.
  974. X */
  975. X
  976. X
  977. X/*
  978. X * MODIFICATION HISTORY
  979. X *
  980. X * 000 -- M. Gancarz, DEC Ultrix Engineering Group
  981. X * 001 -- Loretta Guarino Reid, DEC Ultrix Engineering Group
  982. X *  Western Software Lab. Convert to X11.
  983. X * 002 -- Jordan Hubbard, U.C. Berkeley. New keywords. Menu
  984. X * changes, gadget boxes, title bars, the kitchen sink.
  985. X * 1.6 -- Memory leaks fixed.
  986. X */
  987. X
  988. X%{
  989. X
  990. X
  991. X
  992. X
  993. X#ifndef lint
  994. Xstatic char *rcsid_gram_y = "$Header: /usr/graph2/X11.3/contrib/windowmgrs/awm/RCS/gram.y,v 1.2 89/02/07 21:25:05 jkh Exp $";
  995. X#endif    lint
  996. X
  997. X#include "X11/Xlib.h"
  998. X#include "X11/Xutil.h"
  999. X#include "awm.h"
  1000. X#include <signal.h>
  1001. X
  1002. X/*
  1003. X * Values returned by complex expression parser.
  1004. X */
  1005. X#define C_STRING    1    /* IsString. */
  1006. X#define C_MENU        2    /* IsMenu. */
  1007. X#define C_MAP        3    /* IsMap. */
  1008. X#define C_MENUMAP    4    /* IsMenuMap */
  1009. X#define C_PIXMAP    5    /* IsPixmap */
  1010. X#define C_ACTION    6    /* IsAction */
  1011. X#define GADGET_TOKEN "gadget"
  1012. X
  1013. X     static int ki;            /* Keyword index. */
  1014. X     static int gadgnum;        /* # of gadget we're initing */
  1015. X     static int g_offset;        /* The gadget offset specified */
  1016. X     static int g_gravity;        /* The gadget gravity specified */
  1017. X     static char *g_forecolor;        /* gadget foreground color */
  1018. X     static char *g_backcolor;        /* gadget background color */
  1019. X     static XFontStruct *g_font;    /* gadget font */
  1020. X     static int bkmask;            /* Button/key mask. */
  1021. X     static int cmask;            /* Context mask. */
  1022. X     static char msg[BUFSIZ];        /* Error message buffer. */
  1023. X     static char *menu_name;        /* Menu name. */
  1024. X     static char *menu_pixmap;        /* Name of pixmap for menu label */
  1025. X     static MenuInfo *menu_info;    /* Menu info. */
  1026. X     static ActionLine *ml_ptr;        /* Temporary menu line pointer. */
  1027. X     static ActionLine *action;        /* Temporary action pointer */
  1028. X     MenuLink *menu_link;        /* Temporary menu link pointer. */
  1029. X     GadgetDecl **Gadgets;        /* Pointer to gadget info structs */
  1030. X     char *calloc();
  1031. X
  1032. X     %}
  1033. X
  1034. X%union {
  1035. X     char *sval;
  1036. X     int ival;
  1037. X     short shval;
  1038. X     struct _actionline *alval;
  1039. X     struct _menuinfo *mival;
  1040. X     char **cval;
  1041. X}
  1042. X
  1043. X%token NL
  1044. X     %token <sval> STRING
  1045. X     %token <ival> COMMENT
  1046. X     %type <sval> pixmap_file
  1047. X     %type <ival> gadget_subscript
  1048. X     %type <ival> keyword
  1049. X     %type <ival> compexpr
  1050. X     %type <ival> keyexpr
  1051. X     %type <ival> kmask
  1052. X     %type <ival> contexpr
  1053. X     %type <ival> contmask
  1054. X     %type <ival> buttmodexpr
  1055. X     %type <ival> buttmodifier
  1056. X     %type <ival> buttexpr
  1057. X     %type <sval> menuname
  1058. X     %type <sval> strings
  1059. X     %type <alval> textaction
  1060. X     %type <alval> menuexpr
  1061. X     %type <alval> menulist
  1062. X     %type <alval> menuline
  1063. X     %type <alval> menuaction
  1064. X
  1065. X     %%    /* beginning of rules section */
  1066. X     
  1067. X input:    |    input command
  1068. X     |    input error command { yyerrok; }
  1069. X;
  1070. X
  1071. X command:    boolvar term
  1072. X     |    expr term
  1073. X     |    COMMENT    { Lineno++; }
  1074. X     |    term
  1075. X     ;
  1076. X
  1077. X term:        NL    { Lineno++; }
  1078. X|    ';'
  1079. X     ;
  1080. X
  1081. X expr:        keyword '=' compexpr
  1082. X{
  1083. X     switch (KeywordTable[$1].type) {
  1084. X     case IsQuitFunction:
  1085. X     case IsFunction:
  1086. X      if ($3 == C_MAP) {
  1087. X           bindtofunc($1, bkmask, cmask, NULL);
  1088. X      } else yyerror("illegal construct");
  1089. X      break;
  1090. X
  1091. X     case IsDownFunction:
  1092. X      if (bkmask & ButtonUp) {
  1093. X           sprintf(msg,
  1094. X               "cannot bind %s to button up",
  1095. X               KeywordTable[$1].name);
  1096. X           yyerror(msg);
  1097. X      }
  1098. X      if ($3 == C_MAP) {
  1099. X           bindtofunc($1, bkmask, cmask, NULL);
  1100. X      } else yyerror("illegal construct");
  1101. X      break;
  1102. X
  1103. X     case IsMenuMap:
  1104. X      if (bkmask & ButtonUp) {
  1105. X           sprintf(msg,
  1106. X               "cannot bind %s to button up",
  1107. X               KeywordTable[$1].name);
  1108. X           yyerror(msg);
  1109. X      }
  1110. X      if ($3 == C_MENUMAP) {
  1111. X           bindtofunc
  1112. X            ($1, bkmask, cmask, menu_name);
  1113. X      } else yyerror("illegal construct");
  1114. X      break;
  1115. X
  1116. X     case IsAction:
  1117. X      if ($3 == C_ACTION) {
  1118. X           /*
  1119. X        * We pass a structure pointer here where a char pointer
  1120. X        * is supposed to go. It was a hack, what can I say.
  1121. X        */
  1122. X           bindtofunc
  1123. X            ($1, bkmask, cmask, (char *)action);
  1124. X      } else yyerror("illegal construct");
  1125. X      break;
  1126. X
  1127. X     case IsMenu:
  1128. X      if ($3 == C_MENU) {
  1129. X           /*
  1130. X        * create a menu definition entry.
  1131. X        */
  1132. X           menu_info = stashmenuinfo(menu_name, ml_ptr, menu_pixmap);
  1133. X           menu_link = stashmenulink(menu_info);
  1134. X           Menus = appendmenulink(Menus, menu_link);
  1135. X      } else yyerror("illegal menu construct");
  1136. X      break;
  1137. X
  1138. X     case IsGadget:
  1139. X      if (gadgnum < 0) {
  1140. X           sprintf(msg, "Gadget number must be >= 0\n");
  1141. X           yyerror(msg);
  1142. X      }
  1143. X      /* Bump NumGadgets if necessary */
  1144. X      else if (gadgnum >= NumGadgets)
  1145. X           NumGadgets = gadgnum + 1;
  1146. X      if (NumGadgets > MAX_GADGETS) {
  1147. X           sprintf(msg, "\"numgadgets\" (%d) is > MAX_GADGETS (%d)\n",
  1148. X               NumGadgets, MAX_GADGETS);
  1149. X           yyerror(msg);
  1150. X      }
  1151. X      else {
  1152. X           if ($3 != C_STRING && $3 != C_PIXMAP)
  1153. X            yyerror("Illegal gadget assignment");
  1154. X           else
  1155. X            stashGadget(gadgnum, yylval.sval, $3);
  1156. X      }
  1157. X      break;
  1158. X
  1159. X     default:
  1160. X      yyerror("internal binding error");
  1161. X      break;
  1162. X     }
  1163. X}
  1164. X;
  1165. X pixmap_file:    '(' STRING ')' {
  1166. X      $$ = $2;
  1167. X }
  1168. X;
  1169. X compexpr:    keyexpr ':' contexpr ':' buttexpr
  1170. X{
  1171. X     $$ = C_MAP;
  1172. X     bkmask = $1 | $5;
  1173. X     cmask = $3;
  1174. X}
  1175. X|    keyexpr ':' contexpr ':' buttexpr ':' menuname
  1176. X{
  1177. X     $$ = C_MENUMAP;
  1178. X     bkmask = $1 | $5;
  1179. X     cmask = $3;
  1180. X     menu_name = $7;
  1181. X}
  1182. X|    keyexpr ':' contexpr ':' buttexpr ':' textaction
  1183. X{
  1184. X     $$ = C_ACTION;
  1185. X     bkmask = $1 | $5;
  1186. X     cmask = $3;
  1187. X     action = $7;
  1188. X}
  1189. X|    STRING menuexpr
  1190. X{
  1191. X     $$ = C_MENU;
  1192. X     menu_name = $1;
  1193. X     menu_pixmap = 0;
  1194. X     ml_ptr = $2;
  1195. X}
  1196. X|    pixmap_file STRING menuexpr
  1197. X{
  1198. X     $$ = C_MENU;
  1199. X     menu_name = $2;
  1200. X     menu_pixmap = $1;
  1201. X     ml_ptr = $3;
  1202. X}
  1203. X|    STRING '^' gadgetspec
  1204. X{ yylval.sval = $1; $$ = C_STRING; }
  1205. X|    pixmap_file '^' gadgetspec
  1206. X{ yylval.sval = $1; $$ = C_PIXMAP; }
  1207. X|    STRING
  1208. X{
  1209. X     $$ = C_STRING;
  1210. X     /* just in case it's a gadget, set defaults */
  1211. X     g_forecolor = Foreground;
  1212. X     g_backcolor = Background;
  1213. X     g_gravity = NoGadgetGravity;
  1214. X     g_offset = 0;
  1215. X     g_font = 0;
  1216. X}
  1217. X|    pixmap_file
  1218. X{
  1219. X     $$ = C_PIXMAP;
  1220. X     /* just in case it's a gadget, set defaults */
  1221. X     g_forecolor = Foreground;
  1222. X     g_backcolor = Background;
  1223. X     g_gravity = NoGadgetGravity;
  1224. X     g_offset = 0;
  1225. X     g_font = 0;
  1226. X}     
  1227. X;
  1228. X gadgetspec:     offset
  1229. X|  offset '|' gravity
  1230. X|  offset '|' gravity '|' forecolor
  1231. X|  offset '|' gravity '|' forecolor '|' backcolor
  1232. X|  offset '|' gravity '|' forecolor '|' backcolor '|' fontspec
  1233. X;
  1234. X offset: /* empty */
  1235. X{ g_offset = 0; }
  1236. X| STRING
  1237. X{
  1238. X    g_offset = y_atoi($1);
  1239. X    g_gravity = NoGadgetGravity;
  1240. X    g_forecolor = Foreground;
  1241. X    g_backcolor = Background;
  1242. X    g_font = (XFontStruct *)NULL;
  1243. X}
  1244. X;
  1245. X gravity: /* empty */
  1246. X{ g_gravity = NoGadgetGravity; }
  1247. X| STRING
  1248. X{
  1249. X    g_gravity = gravitylookup($1);
  1250. X    g_forecolor = Foreground;
  1251. X    g_backcolor = Background;
  1252. X    g_font = (XFontStruct *)NULL;
  1253. X}
  1254. X;
  1255. X forecolor: /* empty */
  1256. X{ g_forecolor = Foreground; }
  1257. X| STRING
  1258. X{
  1259. X    g_forecolor = $1;
  1260. X    g_backcolor = Background;
  1261. X    g_font = (XFontStruct *)NULL;
  1262. X}
  1263. X;
  1264. X backcolor: /* empty */
  1265. X{ g_backcolor = Background; }
  1266. X| STRING
  1267. X{
  1268. X    g_backcolor = $1;
  1269. X    g_font = (XFontStruct *)NULL;
  1270. X}
  1271. X;
  1272. X fontspec: /* empty */
  1273. X{ g_font = 0; }
  1274. X| STRING
  1275. X{
  1276. X     g_font = XLoadQueryFont(dpy, $1);
  1277. X     if (!g_font) {
  1278. X      sprintf(msg, "Can't open gadget font '%s'\n", $1);
  1279. X      yywarn(msg);
  1280. X     }
  1281. X}
  1282. X;
  1283. X
  1284. X boolvar:    STRING
  1285. X{
  1286. X     ki = keywordlookup(yylval.sval);
  1287. X     switch (KeywordTable[ki].type) {
  1288. X     case IsParser:
  1289. X      (*KeywordTable[ki].fptr)();
  1290. X      break;
  1291. X     default:
  1292. X      yyerror("keyword error");
  1293. X     }
  1294. X}
  1295. X;
  1296. X
  1297. X keyword:    STRING    {
  1298. X      $$ = keywordlookup(yylval.sval);
  1299. X }
  1300. X|    STRING gadget_subscript {
  1301. X     char *ptr;
  1302. X     char *malloc();
  1303. X
  1304. X     ptr = malloc(strlen(GADGET_TOKEN) + 1);
  1305. X     if (ptr == NULL) {
  1306. X       Error("out of space");
  1307. X     }
  1308. X     strcpy(ptr, GADGET_TOKEN);
  1309. X     $$ = keywordlookup(ptr);
  1310. X     gadgnum = $2;
  1311. X}
  1312. X;
  1313. X
  1314. X gadget_subscript:    '[' STRING ']' {
  1315. X      $$ = y_atoi(yylval.sval);
  1316. X }
  1317. X;
  1318. X
  1319. X keyexpr:    /* empty */
  1320. X{ $$ = 0; }
  1321. X|    kmask
  1322. X{ $$ = $1; }
  1323. X|    kmask '|' keyexpr
  1324. X{ $$ = $1 | $3; }
  1325. X;
  1326. X
  1327. X contexpr:    /* empty */
  1328. X{ $$ = 0xffffffff; }
  1329. X|    contmask
  1330. X{ $$ = $1; }
  1331. X|    contmask '|' contexpr
  1332. X{ $$ = $1 | $3; }
  1333. X;
  1334. X
  1335. X buttexpr:    buttmodexpr
  1336. X{ $$ = CheckButtonState($1); }
  1337. X;
  1338. X
  1339. X kmask:        STRING { $$ = keyexprlookup(yylval.sval); }
  1340. X
  1341. X contmask:    STRING
  1342. X{ $$ = contexprlookup(yylval.sval); }
  1343. X|    STRING gadget_subscript
  1344. X{ 
  1345. X     if ($2 < 0 || $2 >= NumGadgets) {
  1346. X      sprintf(msg, "Bad subscript, gadget #%d must be >= 0 and < %d\n",
  1347. X          $2, NumGadgets);
  1348. X      yyerror(msg);
  1349. X     }
  1350. X     else {
  1351. X         char *ptr;
  1352. X     char *malloc();
  1353. X
  1354. X     ptr = malloc(strlen(GADGET_TOKEN) + 1);
  1355. X     if (ptr == NULL) {
  1356. X       Error("out of space");
  1357. X     }
  1358. X     strcpy(ptr, GADGET_TOKEN);
  1359. X      $$ = contexprlookup(ptr) | (1 << (BITS_USED + $2));
  1360. X     }
  1361. X}
  1362. X;
  1363. X buttmodexpr:     buttmodifier
  1364. X{ $$ = $1; }
  1365. X|    buttmodexpr buttmodifier
  1366. X{ $$ = $1 | $2; }
  1367. X;
  1368. X
  1369. X buttmodifier:    STRING
  1370. X{ $$ = buttexprlookup(yylval.sval); }
  1371. X;
  1372. X
  1373. X menuname:    STRING
  1374. X{ $$ = $1; }
  1375. X;
  1376. X
  1377. X menuexpr:    '{' menulist '}'
  1378. X{ $$ = $2; }
  1379. X;
  1380. X
  1381. X menulist:    menuline
  1382. X{ $$ = $1; }
  1383. X|    menulist menuline
  1384. X{ $$ = appendmenuline($1, $2); }
  1385. X|    menulist COMMENT
  1386. X{
  1387. X     Lineno++;
  1388. X     $$ = $1;
  1389. X}
  1390. X|    COMMENT
  1391. X{
  1392. X     Lineno++;
  1393. X     $$ = NULL;
  1394. X}
  1395. X|    term
  1396. X{ $$ = NULL; }
  1397. X|    menulist term
  1398. X{ $$ = $1; }
  1399. X|    error term
  1400. X{
  1401. X     $$ = NULL;
  1402. X     yyerrok;
  1403. X}
  1404. X;
  1405. X
  1406. X menuline:    strings ':' menuaction term
  1407. X{
  1408. X     $3->name = $1;
  1409. X     $3->pixmapname = (char *)0;
  1410. X     $$ = $3;
  1411. X}
  1412. X|    '(' strings ')' ':' menuaction term
  1413. X{
  1414. X     $5->pixmapname = $2;
  1415. X     $5->name = $2;
  1416. X     $$ = $5;
  1417. X}
  1418. X;
  1419. X
  1420. X menuaction:    STRING
  1421. X{
  1422. X     ki = keywordlookup(yylval.sval);
  1423. X     if ((ki != -1) &&
  1424. X     (KeywordTable[ki].type != IsFunction) &&
  1425. X     (KeywordTable[ki].type != IsImmFunction) &&
  1426. X     (KeywordTable[ki].type != IsQuitFunction) &&
  1427. X     (KeywordTable[ki].type != IsBoolean) &&
  1428. X     (KeywordTable[ki].type != IsDownFunction)) {
  1429. X      sprintf(msg,
  1430. X          "menu action \"%s\" not a function or variable",
  1431. X          KeywordTable[ki].name);
  1432. X      yyerror(msg);
  1433. X     }
  1434. X     ml_ptr = AllocActionLine();
  1435. X     if (KeywordTable[ki].type == IsQuitFunction ||
  1436. X    KeywordTable[ki].type == IsImmFunction)
  1437. X      ml_ptr->type = IsImmFunction;
  1438. X     else if (KeywordTable[ki].type == IsBoolean) {
  1439. X      ml_ptr->type = IsVar;
  1440. X      ml_ptr->text = (char *)KeywordTable[ki].bptr;
  1441. X     }
  1442. X     else
  1443. X      ml_ptr->type = IsUwmFunction;
  1444. X     ml_ptr->func = KeywordTable[ki].fptr;
  1445. X     $$ = ml_ptr;
  1446. X}
  1447. X|    STRING ':' menuname
  1448. X{
  1449. X     ki = keywordlookup($1);
  1450. X     if (ki != -1 &&
  1451. X     KeywordTable[ki].type != IsMenuMap) {
  1452. X      sprintf(msg,
  1453. X          "menu action \"%s\" not a menu function",
  1454. X          KeywordTable[ki].name);
  1455. X      yyerror(msg);
  1456. X     }
  1457. X     ml_ptr = AllocActionLine();
  1458. X     ml_ptr->type = IsMenuFunction;
  1459. X     ml_ptr->text = $3;
  1460. X     $$ = ml_ptr;
  1461. X}
  1462. X|    textaction
  1463. X{ $$ = $1; }
  1464. X;
  1465. X
  1466. X textaction: '!' strings
  1467. X{
  1468. X     $$ = StashActionLine(IsShellCommand, $2);
  1469. X}
  1470. X|    '^' strings
  1471. X{
  1472. X     $$ = StashActionLine(IsTextNL, $2);
  1473. X}
  1474. X|    '|' strings
  1475. X{
  1476. X     $$ = StashActionLine(IsText, $2);
  1477. X}
  1478. X;
  1479. X
  1480. X strings:    STRING    { $$ = yylval.sval; }
  1481. X|    strings STRING
  1482. X{ $$ = strconcat($1, $2); }
  1483. X;
  1484. X
  1485. X%%
  1486. X
  1487. X/*
  1488. X * Look up color named by "string" and return pixel value.
  1489. X */
  1490. XPixel LookupColor(string, cmap, fail)
  1491. Xchar *string;
  1492. XColormap cmap;
  1493. XBoolean *fail;
  1494. X{
  1495. X     XColor vis_ret, act_ret;
  1496. X
  1497. X     Entry("LookupColor")
  1498. X
  1499. X     if (!(string && XParseColor(dpy, cmap, string, &vis_ret, &act_ret) &&
  1500. X    XAllocColor(dpy, cmap, &vis_ret))) {
  1501. X     sprintf(msg, "Can't allocate color '%s', using default\n", string);
  1502. X     yywarn(msg);
  1503. X     if (fail)
  1504. X          *fail = TRUE;
  1505. X     Leave((Pixel)0)
  1506. X     }
  1507. X     if (fail)
  1508. X      *fail = FALSE;
  1509. X     Leave(vis_ret.pixel)
  1510. X}
  1511. X
  1512. X/*
  1513. X * Like LookupColor, but provides its own fallback in case of failure
  1514. X * (currently 0).
  1515. X */
  1516. XPixel GetPixel(string, cmap)
  1517. Xchar *string;
  1518. XColormap cmap;
  1519. X{
  1520. X     XColor vis_ret;
  1521. X
  1522. X     Entry("GetPixel")
  1523. X
  1524. X     if (!string)
  1525. X     Leave((Pixel)0)
  1526. X     if (!(string && XParseColor(dpy, cmap, string, &vis_ret) &&
  1527. X    XAllocColor(dpy, cmap, &vis_ret)))
  1528. X     Leave((Pixel)0)
  1529. X     Leave(vis_ret.pixel)
  1530. X}
  1531. X
  1532. X/*
  1533. X * Look up a string in the keyword table and return its index, else
  1534. X * return -1.
  1535. X */
  1536. Xint keywordlookup(string)
  1537. Xchar *string;
  1538. X{
  1539. X     int i;
  1540. X     
  1541. X     Entry("keywordlookup")
  1542. X
  1543. X     for (i = 0; KeywordTable[i].name; i++) {
  1544. X          if (!strcmp(KeywordTable[i].name, string)) {
  1545. X           free(string);
  1546. X           Leave(i)
  1547. X      }
  1548. X     }
  1549. X     sprintf(msg,"keyword error: \"%s\"", string);
  1550. X     yyerror(msg);
  1551. X     free(string);
  1552. X     Leave(-1)
  1553. X}
  1554. X
  1555. X/*
  1556. X * Look up a string in the key expression table and return its mask, else
  1557. X * return -1.
  1558. X */
  1559. Xint keyexprlookup(string)
  1560. Xchar *string;
  1561. X{
  1562. X     int i;
  1563. X     
  1564. X     Entry("keyexprlookup")
  1565. X
  1566. X     for (i = 0; KeyExprTbl[i].name; i++) {
  1567. X      if (!strcmp(KeyExprTbl[i].name, string)) {
  1568. X           free(string);
  1569. X           Leave(KeyExprTbl[i].mask)
  1570. X      }
  1571. X     }
  1572. X     sprintf(msg,"key expression error: \"%s\"", string);
  1573. X     yyerror(msg);
  1574. X     free(string);
  1575. X     Leave(-1)
  1576. X}
  1577. X
  1578. Xint gravitylookup(string)
  1579. Xchar *string;
  1580. X{
  1581. X     int i;
  1582. X
  1583. X     Entry("gravitylookup")
  1584. X
  1585. X     for (i = 0; GravityExprTbl[i].name; i++) {
  1586. X      if (!strcmp(GravityExprTbl[i].name, string)) {
  1587. X           free(string);
  1588. X           Leave(GravityExprTbl[i].mask)
  1589. X      }
  1590. X     }
  1591. X     sprintf(msg, "gravity expression error: \"%s\"", string);
  1592. X     yyerror(msg);
  1593. X     free(string);
  1594. X     Leave(-1);
  1595. X}
  1596. X    
  1597. X/*
  1598. X * Look up a string in the context expression table and return its mask, else
  1599. X * return -1.
  1600. X */
  1601. Xcontexprlookup(string)
  1602. Xchar *string;
  1603. X{
  1604. X     int i;
  1605. X     
  1606. X     Entry("contexprlookup")
  1607. X
  1608. X     for (i = 0; ContExprTbl[i].name; i++) {
  1609. X      if (!strcmp(ContExprTbl[i].name, string)) {
  1610. X           free(string);
  1611. X           Leave(ContExprTbl[i].mask)
  1612. X      }
  1613. X     }
  1614. X     sprintf(msg,"context expression error: \"%s\"", string);
  1615. X     yyerror(msg);
  1616. X     free(string);
  1617. X     Leave(-1)
  1618. X}
  1619. X
  1620. X/*
  1621. X * Look up a string in the button expression table and return its mask, else
  1622. X * return -1.
  1623. X */
  1624. Xbuttexprlookup(string)
  1625. Xchar *string;
  1626. X{
  1627. X     int i;
  1628. X     
  1629. X     Entry("buttexprlookup")
  1630. X
  1631. X     for (i = 0; ButtModTbl[i].name; i++) {
  1632. X      if (!strcmp(ButtModTbl[i].name, string)) {
  1633. X           free(string);
  1634. X           Leave(ButtModTbl[i].mask)
  1635. X      }
  1636. X     }
  1637. X     sprintf(msg,"button modifier error: \"%s\"", string);
  1638. X     yyerror(msg);
  1639. X     free(string);
  1640. X     Leave(-1)
  1641. X}
  1642. X
  1643. X/*
  1644. X * Scan a string and return an integer.  Report an error if any
  1645. X * non-numeric characters are found.
  1646. X */
  1647. Xy_atoi(s)
  1648. Xchar *s;
  1649. X{
  1650. X     int n = 0;
  1651. X     
  1652. X     Entry("y_atoi")
  1653. X
  1654. X     while (*s) {
  1655. X      if (*s >= '0' && *s <= '9')
  1656. X           n = 10 * n + *s - '0';
  1657. X      else {
  1658. X           yyerror("non-numeric argument");
  1659. X           Leave(-1)
  1660. X      }
  1661. X      s++;
  1662. X     }
  1663. X     Leave(n)
  1664. X}
  1665. X
  1666. X/*
  1667. X * Append s2 to s1, extending s1 as necessary.
  1668. X */
  1669. Xchar *
  1670. X     strconcat(s1, s2)
  1671. Xchar *s1, *s2;
  1672. X{
  1673. X     char *malloc();
  1674. X     char *p;
  1675. X     
  1676. X     Entry("strconcat")
  1677. X
  1678. X     p = malloc(strlen(s1) + strlen(s2) + 2);
  1679. X     sprintf(p, "%s %s", s1, s2);
  1680. X     free(s1);
  1681. X     free(s2);
  1682. X     s1 = p;
  1683. X     Leave(s1)
  1684. X}
  1685. X
  1686. X/*
  1687. X * Check a button expression for errors.
  1688. X */
  1689. Xint CheckButtonState(expr)
  1690. Xint expr;
  1691. X{
  1692. X     Entry("CheckButtonState")
  1693. X
  1694. X     /*
  1695. X      * Check for one (and only one) button.
  1696. X      */
  1697. X     switch (expr & (LeftMask | MiddleMask | RightMask)) {
  1698. X     case 0:
  1699. X      yyerror("no button specified");
  1700. X      break;
  1701. X     case LeftMask:
  1702. X      break;
  1703. X     case MiddleMask:
  1704. X      break;
  1705. X     case RightMask:
  1706. X      break;
  1707. X     default:
  1708. X      yyerror("more than one button specified");
  1709. X     }
  1710. X     
  1711. X     /*
  1712. X      * Check for one (and only one) up/down/motion modifier.
  1713. X      */
  1714. X     switch (expr & (ButtonUp | ButtonDown | DeltaMotion)) {
  1715. X     case 0:
  1716. X      yyerror("no button action specified");
  1717. X      break;
  1718. X     case ButtonUp:
  1719. X      break;
  1720. X     case ButtonDown:
  1721. X      break;
  1722. X     case DeltaMotion:
  1723. X      break;
  1724. X     default:
  1725. X      yyerror("only one of up/down/motion may be specified");
  1726. X     }
  1727. X     Leave(expr)
  1728. X}
  1729. X
  1730. X/*
  1731. X * Bind button/key/context to a function.
  1732. X */
  1733. Xbindtofunc(index, mask, context, name)
  1734. Xint index;        /* Index into keyword table. */
  1735. Xint mask;        /* Button/key/modifier mask. */
  1736. Xint context;        /* ROOT, WINDOW, TITLE, ICON, GADGET or BORDER */
  1737. Xchar *name;        /* Menu, if needed. */
  1738. X{
  1739. X     Entry("bindtofunc")
  1740. X
  1741. X     setbinding(context, index, mask, name);
  1742. X     Leave_void
  1743. X}
  1744. X
  1745. X/*
  1746. X * Allocate a Binding type and return a pointer.
  1747. X */
  1748. XBinding *
  1749. X     AllocBinding()
  1750. X{
  1751. X     Binding *ptr;
  1752. X     
  1753. X     Entry("AllocBinding")
  1754. X
  1755. X     if (!(ptr = (Binding *)calloc(1, sizeof(Binding)))) {
  1756. X      sprintf(msg, "Can't allocate binding--out of space\n");
  1757. X      yyerror(msg);
  1758. X      exit(1);
  1759. X     }
  1760. X     Leave(ptr)
  1761. X}
  1762. X
  1763. X/*
  1764. X * Stash the data in a Binding.
  1765. X */
  1766. Xsetbinding(cont, i, m, mname)
  1767. Xint cont;        /* Context: ROOT, WINDOW, or ICON. */
  1768. Xint i;            /* Keyword table index. */
  1769. Xint m;        /* Key/button/modifier mask. */
  1770. Xchar *mname;        /* Pointer to menu name, if needed. */
  1771. X{
  1772. X     Binding *ptr;
  1773. X
  1774. X     Entry("setbinding")
  1775. X
  1776. X     ptr = AllocBinding();
  1777. X     ptr->context = cont;
  1778. X     ptr->mask = m;
  1779. X     ptr->func = KeywordTable[i].fptr;
  1780. X     ptr->menuname = mname;
  1781. X     switch (m & (LeftMask | MiddleMask | RightMask)) {
  1782. X     case LeftMask:
  1783. X      ptr->button = LeftButton;
  1784. X      break;
  1785. X     case MiddleMask:
  1786. X      ptr->button = MiddleButton;
  1787. X      break;
  1788. X     case RightMask:
  1789. X      ptr->button = RightButton;
  1790. X      break;
  1791. X     }
  1792. X     appendbinding(ptr);
  1793. X     Leave_void
  1794. X}
  1795. X
  1796. X/*
  1797. X * Append a Binding to the Bindings list.
  1798. X */
  1799. Xappendbinding(binding)
  1800. XBinding *binding;
  1801. X{
  1802. X     Binding *ptr;
  1803. X     
  1804. X     Entry("appendbinding")
  1805. X
  1806. X     if (Blist == NULL)
  1807. X      Blist = binding;
  1808. X     else {
  1809. X      for(ptr = Blist; ptr->next; ptr = ptr->next) /* NULL */;
  1810. X      ptr->next = binding;
  1811. X      ptr = ptr->next;
  1812. X      ptr->next = NULL;
  1813. X     }
  1814. X     Leave_void
  1815. X}
  1816. X
  1817. X/*
  1818. X * Allocate an action line and return a pointer.
  1819. X */
  1820. XActionLine *AllocActionLine()
  1821. X{
  1822. X     ActionLine *ptr;
  1823. X     
  1824. X     Entry("AllocActionLine")
  1825. X
  1826. X     if (!(ptr = (ActionLine *)calloc(1, sizeof(ActionLine)))) {
  1827. X      sprintf(msg, "Can't allocate action line--out of space\n");
  1828. X      yyerror(msg);
  1829. X     }
  1830. X     Leave(ptr)
  1831. X}
  1832. X
  1833. X/*
  1834. X * Allocate a MenuInfo structure and return a pointer.
  1835. X */
  1836. XMenuInfo *AllocMenuInfo()
  1837. X{
  1838. X     MenuInfo *ptr;
  1839. X     
  1840. X     Entry("AllocMenuInfo")
  1841. X
  1842. X     if (!(ptr = (MenuInfo *)calloc(1, sizeof(MenuInfo)))) {
  1843. X      sprintf(msg, "Can't allocate menu storage--out of space\n");
  1844. X      yyerror(msg);
  1845. X     }
  1846. X     Leave(ptr)
  1847. X}
  1848. X
  1849. X/*
  1850. X * Allocate a MenuLink structure and return a pointer.
  1851. X */
  1852. XMenuLink *AllocMenuLink()
  1853. X{
  1854. X     MenuLink *ptr;
  1855. X     Entry("AllocMenuLink")
  1856. X
  1857. X     if (!(ptr = (MenuLink *)calloc(1, sizeof(MenuLink)))) {
  1858. X      sprintf(msg, "Can't allocate menu linked list storage--out of space\n");
  1859. X      yyerror(msg);
  1860. X     }
  1861. X     Leave(ptr)
  1862. X}
  1863. X
  1864. X/*
  1865. X * Return storage for Gadgets[] array.
  1866. X */
  1867. XGadgetDecl **allocate_gadgets()
  1868. X{
  1869. X     GadgetDecl **tmp;
  1870. X     int i;
  1871. X
  1872. X     Entry("allocate_gadgets")
  1873. X
  1874. X     tmp = (GadgetDecl **)malloc(MAX_GADGETS * sizeof(GadgetDecl *));
  1875. X     if (!tmp) {
  1876. X      sprintf(msg, "Can't allocate storage for Gadgets -- out of space\n");
  1877. X      yyerror(msg);
  1878. X      Leave(NULL)
  1879. X     }
  1880. X     for (i = 0; i < MAX_GADGETS; i++)
  1881. X      tmp[i] = (GadgetDecl *)0;
  1882. X     Leave(tmp)
  1883. X}
  1884. X
  1885. X/*
  1886. X * Stash a gadget record
  1887. X */
  1888. XGadgetDecl *stashGadget(n, s, type)
  1889. Xint n;
  1890. Xchar *s;
  1891. Xint type;
  1892. X{
  1893. X     GadgetDecl *tmp;
  1894. X
  1895. X     Entry("stashGadget")
  1896. X
  1897. X     if (!Gadgets)
  1898. X      Gadgets = (GadgetDecl **)allocate_gadgets();
  1899. X     if (n < 0 || n >= NumGadgets) {
  1900. X      sprintf(msg, "stashGadget on gadget #%d when maxgadget = %d\n",
  1901. X          n, NumGadgets);
  1902. X      yyerror(msg);
  1903. X      Leave(NULL)
  1904. X     }
  1905. X     if (Gadgets[n]) {
  1906. X      sprintf(msg, "gadget #%d redefined\n", n);
  1907. X      yywarn(msg);
  1908. X      FreeGadget(n);
  1909. X          tmp = Gadgets[n];
  1910. X     }
  1911. X     else
  1912. X      Gadgets[n] = tmp = (GadgetDecl *)malloc(sizeof(GadgetDecl));
  1913. X     if (!Gadgets[n]) {
  1914. X      sprintf(msg, "Can't allocate new gadget, out of space!\n");
  1915. X      yyerror(msg);
  1916. X      Leave(NULL)
  1917. X     }
  1918. X     tmp->data = (unsigned char *)NULL;
  1919. X     tmp->name = (unsigned char *)NULL;
  1920. X     tmp->high = tmp->wide = 0;
  1921. X     tmp->gravity = g_gravity;
  1922. X     tmp->offset = g_offset;
  1923. X     tmp->forecolor = g_forecolor;
  1924. X     tmp->backcolor = g_backcolor;
  1925. X     tmp->fontInfo = g_font;
  1926. X     if (type != C_STRING && type != C_PIXMAP) {
  1927. X      sprintf(msg, "Invalid gadget specification for gadget #%d\n", n);
  1928. X      yyerror(msg);
  1929. X      NumGadgets = 0;
  1930. X          Leave(NULL)
  1931. X     }
  1932. X     if (type == C_PIXMAP) {
  1933. X      int junk;
  1934. X      char *nm = s;
  1935. X
  1936. X      s = expand_from_path(s);
  1937. X      if (!s) {
  1938. X           sprintf(msg, "Can't find pixmap file '%s' for gadget #%d\n",
  1939. X               nm, n);
  1940. X           yywarn(msg);
  1941. X           tmp->data = (unsigned char *)gray_bits;
  1942. X           tmp->high = gray_height;
  1943. X           tmp->wide = gray_width;
  1944. X      }
  1945. X      else if (XmuReadBitmapDataFromFile (s, &(tmp->wide),
  1946. X                  &(tmp->high), &(tmp->data), &junk, &junk)
  1947. X          != BitmapSuccess) {
  1948. X           sprintf(msg, "Can't open pixmap file '%s' for gadget #%d.\n", s, n);
  1949. X           yyerror(msg);
  1950. X           tmp->data = (unsigned char *)gray_bits;
  1951. X           tmp->high = gray_height;
  1952. X           tmp->wide = gray_width;
  1953. X      }
  1954. X      if (tmp->high > gadgetHeight)
  1955. X           gadgetHeight = tmp->high;
  1956. X     }
  1957. X     else if (type == C_STRING) { /* it's a label */
  1958. X      tmp->name = expand_metachars(s);
  1959. X      if (!tmp->fontInfo) {
  1960. X           if (!GFontInfo) {
  1961. X            GFontInfo = GetFontRes("gadget.font", DEF_GADGET_FONT);
  1962. X            if (!GFontInfo) {
  1963. X             sprintf(msg, "Can't get a default gadget font.\n");
  1964. X             yyerror(msg);
  1965. X             Leave(NULL)
  1966. X            }
  1967. X           }
  1968. X           tmp->fontInfo = GFontInfo;
  1969. X      }
  1970. X      if (strlen(tmp->name) > 1) {
  1971. X           tmp->wide = XTextWidth(tmp->fontInfo, tmp->name, strlen(tmp->name));
  1972. X           tmp->high = tmp->fontInfo->max_bounds.ascent +
  1973. X            tmp->fontInfo->max_bounds.descent + 2;
  1974. X      }
  1975. X      else {
  1976. X           XCharStruct chinfo;
  1977. X           int asc, desc, dir;
  1978. X
  1979. X           XTextExtents(tmp->fontInfo, tmp->name, 1, &dir, &asc,
  1980. X                &desc, &chinfo);
  1981. X           tmp->wide = chinfo.width;
  1982. X           tmp->high = chinfo.ascent + chinfo.descent;
  1983. X      }
  1984. X      tmp->wide += 2 * GadgetBorder;
  1985. X          if (tmp->high > gadgetHeight)
  1986. X           gadgetHeight = tmp->high;
  1987. X     }
  1988. X     Leave(tmp)
  1989. X}
  1990. X
  1991. X/*
  1992. X * This routine expands '\' notation in a string, ala C. Mostly useful for
  1993. X * imbedding weird characters in strings that turn into interesting symbols
  1994. X * from some font. Unlike C, however, numeric constants (\nnn) are in
  1995. X * decimal, not octal. This was done because the most popular glyphs
  1996. X * (in cursorfont.h) are identified in decimal. There are some other cute
  1997. X * "metacharacters" that expand to the window name, icon name, etc.
  1998. X */
  1999. Xunsigned char *expand_metachars(s)
  2000. Xregister unsigned char *s;
  2001. X{
  2002. X     register int i, len, val, n;
  2003. X     unsigned char *cp, num[5];
  2004. X
  2005. X     Entry("expand_metachars")
  2006. X
  2007. X     if (!s)
  2008. X      Leave(s)
  2009. X     len = strlen(s);
  2010. X     for (i = 0; i < len; i++)
  2011. X      if (s[i] == '\\')
  2012. X           break;
  2013. X     if (i == len)
  2014. X      Leave(s)
  2015. X     /* we know the string is going to get shorter, len is correct */
  2016. X     cp = (unsigned char *)malloc(len);
  2017. X     i = n = 0;
  2018. X     while (*s) {
  2019. X      if (*s == '\\') {
  2020. X           s++;
  2021. X           while (*s && *s >= '0' && *s <= '9') {
  2022. X            num[n++] = *s;
  2023. X            s++;
  2024. X           }
  2025. X           if (n) {
  2026. X            if (n > 4)
  2027. X             n = 4;
  2028. X            num[n] = '\0';
  2029. X            cp[i++] = (char)atoi(num);
  2030. X            n = 0;
  2031. X           }
  2032. X           else if (*s) {
  2033. X            switch(*s) {
  2034. X
  2035. X            case 'b':
  2036. X             val = 8;
  2037. X             break;
  2038. X
  2039. X            case 'f':
  2040. X             val = 12;
  2041. X
  2042. X            case 'n':
  2043. X             val = 10;
  2044. X             break;
  2045. X
  2046. X            case 'r':
  2047. X             val = 13;
  2048. X             break;
  2049. X
  2050. X            case 't':
  2051. X             val = 9;
  2052. X             break;
  2053. X
  2054. X            default:
  2055. X             val = *s;
  2056. X             break;
  2057. X            }
  2058. X            cp[i++] = val;
  2059. X            s++;
  2060. X           }
  2061. X      }
  2062. X      else {
  2063. X           cp[i++] = *s;
  2064. X           s++;
  2065. X      }
  2066. X     }
  2067. X     cp[i] = '\0';
  2068. X     Leave(cp)
  2069. X}
  2070. X      
  2071. X/*
  2072. X * Stash the data in an action line.
  2073. X */
  2074. XActionLine *StashActionLine(type, string)
  2075. Xint type;
  2076. Xchar *string;
  2077. X{
  2078. X     ActionLine *ptr;
  2079. X     
  2080. X     Entry("StashActionLine")
  2081. X
  2082. X     ptr = AllocActionLine();
  2083. X     ptr->type = type;
  2084. X     ptr->text = string;
  2085. X     Leave(ptr)
  2086. X}
  2087. X
  2088. X/*
  2089. X * Stash menu data in a MenuInfo structure;
  2090. X */
  2091. XMenuInfo *stashmenuinfo(name, line, pixmap)
  2092. Xchar *name;
  2093. XActionLine *line;
  2094. Xchar *pixmap;
  2095. X{
  2096. X     MenuInfo *ptr;
  2097. X     
  2098. X     Entry("stashmenuinfo")
  2099. X
  2100. X     ptr = AllocMenuInfo();
  2101. X     ptr->name = name;
  2102. X     ptr->line = line;
  2103. X     ptr->pixmapname = pixmap;
  2104. X     ptr->menu = 0;
  2105. X     Leave(ptr)
  2106. X}
  2107. X
  2108. X/*
  2109. X * Stash menu info data in a MenuLink structure;
  2110. X */
  2111. XMenuLink *stashmenulink(menuinfo)
  2112. XMenuInfo *menuinfo;
  2113. X{
  2114. X     MenuLink *ptr;
  2115. X     
  2116. X     Entry("stashmenulink")
  2117. X
  2118. X     ptr = AllocMenuLink();
  2119. X     ptr->next = NULL;
  2120. X     ptr->menu = menuinfo;
  2121. X     Leave(ptr)
  2122. X}
  2123. X
  2124. X/*
  2125. X * Append an action line to a linked list of menu lines.
  2126. X */
  2127. XActionLine *appendmenuline(list, line)
  2128. XActionLine *list;
  2129. XActionLine *line;
  2130. X{
  2131. X     ActionLine *ptr;
  2132. X     
  2133. X     Entry("appendmenuline")
  2134. X
  2135. X     if (list == NULL)
  2136. X      list = line;
  2137. X     else {
  2138. X      for(ptr = list; ptr->next; ptr = ptr->next) /* NULL */;
  2139. X      ptr->next = line;
  2140. X      ptr = ptr->next;
  2141. X      ptr->next = NULL;
  2142. X     }
  2143. X     Leave(list)
  2144. X}
  2145. X
  2146. X/*
  2147. X * Append a menu to a linked list of menus.
  2148. X */
  2149. XMenuLink *
  2150. X     appendmenulink(list, link)
  2151. XMenuLink *list;
  2152. XMenuLink *link;
  2153. X{
  2154. X     MenuLink *ptr;
  2155. X     
  2156. X     Entry("appendmenulink")
  2157. X
  2158. X     if (list == NULL)
  2159. X      list = link;
  2160. X     else {
  2161. X      for(ptr = list; ptr->next; ptr = ptr->next) /* NULL */;
  2162. X      ptr->next = link;
  2163. X      ptr = ptr->next;
  2164. X      ptr->next = NULL;
  2165. X     }
  2166. X     Leave(list)
  2167. X}
  2168. X     
  2169. X/*
  2170. X * Reset all previous bindings and free the space allocated to them.
  2171. X */
  2172. XBoolean ResetBindings()
  2173. X{
  2174. X     Binding *ptr, *nextptr;
  2175. X     
  2176. X     Entry("ResetBindings")
  2177. X
  2178. X     for(ptr = Blist; ptr; ptr = nextptr) {
  2179. X      nextptr = ptr->next;
  2180. X      free(ptr);
  2181. X     }
  2182. X     Blist = NULL;
  2183. X     Leave_void
  2184. X}
  2185. X
  2186. X/*
  2187. X * De-allocate all menus.
  2188. X */
  2189. XBoolean ResetMenus()
  2190. X{
  2191. X     MenuLink *mptr, *next_mptr;
  2192. X     register ActionLine *lptr, *next_lptr;
  2193. X     Entry("ResetMenus")
  2194. X     if (!Menus)
  2195. X    Leave_void
  2196. X     for(mptr = Menus; mptr; mptr = next_mptr) {
  2197. X      free(mptr->menu->name);
  2198. X      RTLMenu_Destroy(mptr->menu->menu);
  2199. X      for(lptr = mptr->menu->line; lptr; lptr = next_lptr) {
  2200. X           free(lptr->name);
  2201. X           if (lptr->text) free(lptr->text);
  2202. X           next_lptr = lptr->next;
  2203. X           free(lptr);
  2204. X      }
  2205. X      next_mptr = mptr->next;
  2206. X      free(mptr);
  2207. X     }
  2208. X     Menus = NULL;
  2209. X     Leave_void
  2210. X}
  2211. END_OF_FILE
  2212. if test 27303 -ne `wc -c <'gram.y'`; then
  2213.     echo shar: \"'gram.y'\" unpacked with wrong size!
  2214. fi
  2215. # end of 'gram.y'
  2216. fi
  2217. echo shar: End of archive 4 \(of 12\).
  2218. cp /dev/null ark4isdone
  2219. MISSING=""
  2220. for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
  2221.     if test ! -f ark${I}isdone ; then
  2222.     MISSING="${MISSING} ${I}"
  2223.     fi
  2224. done
  2225. if test "${MISSING}" = "" ; then
  2226.     echo You have unpacked all 12 archives.
  2227.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2228. else
  2229.     echo You still need to unpack the following archives:
  2230.     echo "        " ${MISSING}
  2231. fi
  2232. ##  End of shell archive.
  2233. exit 0
  2234. -- 
  2235. Mike Wexler(wyse!mikew)    Phone: (408)433-1000 x1330
  2236. Moderator of comp.sources.x
  2237.